import { _decorator, assetManager, Component, instantiate, Prefab, Node, Sprite, UITransform, Vec2, v2, resources, SpriteFrame, SpriteComponent, Rect, tween, EventTouch, UIVertexFormat, input, Input, EventKeyboard, Label, Color, Button, KeyCode } from 'cc';
import { Picture } from './Picture';
const { ccclass, property } = _decorator;

@ccclass('GameControl')
export class GameControl extends Component {
    @property(Node)
    startPanel: Node = null;
    @property(Node)
    gamePanel: Node = null;
    @property(Node)
    overPanel: Node = null;

    @property(Node)
    midPanel: Node = null;

    @property(Prefab)
    picFab: Prefab = null;

    private itemWidth: number = 0;
    private itemParentWh: number = 0;
    private space: number = 2;
    private gameLevel = 6;

    // 定义一个二维数组来存放图片顺序 [x][y] = x*100 + y 则成功
    private picArray = [];
    private picStatus = [];
    private midNodePos = null;

    private posStart;
    private posEnd;
    private stepNum:number = 0;

    /**
     * 启动执行一次
     */
    start() {
        this.initPanel();
        this.gamePanel.active = true;
        this.initPosition();
        this.initEvent();
        this.createGamePanel();

        // 二维旋转 this.node.angle
        // 位置this.node.position
        // 三维旋转this.node.rotation
        // 缩放this.node.scale

        // 缓动系统,用来做动画。譬如节点的移动
        // const obj = {n:0};
        // let t = tween(obj);
        // t.to(3, {n:1000}, {onUpdate: (target, ratio)=>{
        //         console.log(target, ratio);
        //     },easing:'quadIn'   // 设置效果
        // }).union()
        // .repeatForever()    // 重复
        // .start();

        // // 动画停止
        // t.stop()

        // // 获取节点的UITransform
        // const tf = this.node.getComponent(UITransform);
        // // 转换到基于节点的三维空间,既节点的中间坐标为(0,0)
        // tf.convertToNodeSpaceAR();

        // // 监听触摸事件
        // this.node.on(Node.EventType.TOUCH_START, (event:EventTouch)=>{
        //     // 获取控件的位置(最小角为0,0)
        //     event.getUILocation();
        //     // 中心点为(0,0)
        //     event.getLocation(); 
        //     // 获取屏幕的Delta
        //     event.getDeltaX();
        //     // 获取控件
        //     event.getUIDelta().x
        // }, this);

        // 监听键盘的
        // input.on(Input.EventType.KEY_DOWN, (event:EventKeyboard)=>{
        //     console.log(event);
        // });
    }

    /**
     * 每一帧都执行一次
     * @param deltaTime  = 1 / 电脑帧数
     */
    update(deltaTime: number) {
    }

    private initPosition() {
        // 计算每个小块的宽度
        this.itemWidth = Math.round(720 / this.gameLevel);
        // 计算全部的宽度
        this.itemParentWh = this.itemWidth * this.gameLevel + this.space * (this.gameLevel - 1); // 计算总的长宽
        let midTf = this.midPanel.getComponent(UITransform);
        midTf.width = this.itemParentWh;
        midTf.height = this.itemParentWh;
        this.itemWidth = (this.itemParentWh - this.space * (this.gameLevel - 1)) / this.gameLevel;
    }

    // 初始化显示界面
    private initPanel() {
        this.startPanel.active = false;
        this.gamePanel.active = false;
        this.overPanel.active = false;
    }

    /**
     * 监听事件
     */
    private initEvent() {
        input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
        input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
        input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
        input.on(Input.EventType.TOUCH_CANCEL, this.onTouchCancel, this);

        input.on(Input.EventType.KEY_DOWN, this.onKeyDown, this)
    }

    private onTouchStart(event: EventTouch) {
        this.posStart = event.getLocation();
    }

    private onTouchEnd(event: EventTouch) {
        this.posEnd = event.getLocation();
        let xx = this.posEnd.x - this.posStart.x;
        let yy = this.posEnd.y - this.posStart.y;
        if (Math.abs(xx) < 10 && Math.abs(yy) < 10) {
            return
        }

        if (Math.abs(xx) > Math.abs(yy)) {
            if (xx > 0) {
                this.moveItemPicture(4);// 向右滑动时的逻辑处理
            } else {
                this.moveItemPicture(3);// 向左滑动时的逻辑处理
            }
        } else {
            if (yy > 0) {
                this.moveItemPicture(1);// 向上滑动时的逻辑处理
            } else {
                this.moveItemPicture(2);// 向下滑动时的逻辑处理
            }
        }
    }

    private onTouchMove(event: EventTouch) { }

    private onTouchCancel(event: EventTouch) { }

    private onKeyDown(event: EventKeyboard) {
        if (event.keyCode == KeyCode.ARROW_LEFT) {
            this.moveItemPicture(3)
        }
        if (event.keyCode == KeyCode.ARROW_RIGHT) {
            this.moveItemPicture(4);
        }
        if (event.keyCode == KeyCode.ARROW_UP) {
            this.moveItemPicture(1);
        }
        if (event.keyCode == KeyCode.ARROW_DOWN) {
            this.moveItemPicture(2);
        }
    }

    /**
     * 移动图片
     * @param moveType 1上，2下，3左，4右
     */
    private moveItemPicture(moveType: number) {
        for (let x = 0; x < this.picStatus.length; x++) {
            for (let y = 0; y < this.picStatus.length; y++) {
                if (this.picStatus[x][y] == 0) {
                    // console.log("(" + x + "," + y + ")=>0");
                    switch (moveType) {
                        case 1: // 上
                            if (x > 0) {
                                this.picStatus[x][y] = this.picStatus[x - 1][y];
                                this.picStatus[x - 1][y] = 0;
                                this.picArray[x][y] = this.picArray[x - 1][y];
                                this.picArray[x - 1][y] = null;
                                this.calcPicPosition(v2(x, y), this.picArray[x][y]);
                            }
                            break;
                        case 2: // 下
                            if ((x + 1) < this.picStatus.length) {
                                this.picStatus[x][y] = this.picStatus[x + 1][y];
                                this.picStatus[x + 1][y] = 0;
                                this.picArray[x][y] = this.picArray[x + 1][y];
                                this.picArray[x + 1][y] = 0;
                                this.calcPicPosition(v2(x, y), this.picArray[x][y]);
                            }
                            break;
                        case 3: // 左
                            if ((y + 1) < this.picStatus.length) {
                                this.picStatus[x][y] = this.picStatus[x][y + 1];
                                this.picStatus[x][y + 1] = 0;
                                this.picArray[x][y] = this.picArray[x][y + 1];
                                this.picArray[x][y + 1] = 0;
                                this.calcPicPosition(v2(x, y), this.picArray[x][y]);
                            }
                            break;
                        case 4: // 右
                            if (y > 0) {
                                this.picStatus[x][y] = this.picStatus[x][y - 1];
                                this.picStatus[x][y - 1] = 0;
                                this.picArray[x][y] = this.picArray[x][y - 1];
                                this.picArray[x][y - 1] = 0;
                                this.calcPicPosition(v2(x, y), this.picArray[x][y]);
                            }
                            break;
                    }
                    this.stepNum++;
                    if (this.win()) {
                        console.log("you are win");
                    }
                    return;
                }
            }
        }
        if (this.win()) {
            console.log("you are win");
        }
        return;
    }

    // 创建游戏界面
    private createGamePanel() {
        // 先清空数组
        this.initArray(this.gameLevel);
        // 从小往上进行显示
        for (let i = 0; i < this.gameLevel; i++) {
            for (let j = 0; j < this.gameLevel; j++) {
                if (i == 0 && j == this.gameLevel - 1) {
                    break; // 最后一张面空缺
                }
                this.createItem(v2(i, j));
            }
        }
        // 打乱方块
        this.randomGame();
    }

    private initArray(lv: number) {
        this.picArray = [];
        this.picStatus = [];
        for (let i = 0; i < lv; i++) {
            this.picArray[i] = [];
            this.picStatus[i] = [];
        }

        for (let i = 0; i < lv; i++) {
            for (let j = 0; j < lv; j++) {
                this.picStatus[i][j] = 0;
                this.picArray[i][j] = null;
            }
        }
    }

    // 创建每一个图片块
    private createItem(pos: Vec2) {
        // 坐标系设置到左下角为(0,0)
        this.midNodePos = v2(-this.itemParentWh / 2 + this.itemWidth / 2 + this.space, -this.itemParentWh / 2 + this.itemWidth / 2 + this.space);
        // 计算node节点的坐标
        let item = instantiate(this.picFab);
        item.parent = this.midPanel;
        // 计算位置
        this.calcPicPosition(pos, item);
        // console.log(pos, "item.x:" + item.position.x + " item.y:" + item.position.y);
        // 裁剪图片
        let picItem = item.getComponent(Picture);
        picItem.init("game.jpg", this.itemWidth, pos, this.gameLevel);

        // 二维数组记录item
        this.picArray[pos.x][pos.y] = item;
        this.picStatus[pos.x][pos.y] = this.calcPicValue(pos.x, pos.y);
    }

    private randomGame() {
        if (this.picArray.length <= 0) {
            return;
        }
        // 随机替换一半以上的块
        let total = this.picArray.length * this.picArray.length;
        for(let i=0 ;i<this.picArray.length; i++) {
            for (let j=0; j<this.picArray.length; j++) {
                let rand = Math.floor((Math.random() * (total-1)));
                let _cx = Math.floor(rand/this.gameLevel);
                let _cy = rand%this.gameLevel;
                this.replace(v2(i,j), v2(_cx, _cy));
            }
        }

        // 最后将空白块，移动到右下角
        for(let i=0 ;i<this.picArray.length; i++) {
            for (let j=0; j<this.picArray.length; j++) {
                if(this.picStatus[i][j] == 0) {
                    this.replace(v2(i,j), v2(0, this.picArray.length-1));
                    return;
                }
            }
        }
    }

    // 从下往上放(0,0)->(4,4)
    private calcPicPosition(pos: Vec2, item: Node) {
        // UI变换组件
        let itemTf: UITransform = item.getComponent(UITransform);
        itemTf.width = this.itemWidth;
        itemTf.height = this.itemWidth;
        // 计算item组件应该放置的位置
        let _x = this.midNodePos.x + (itemTf.width + this.space) * pos.y;  // width
        let _y = this.midNodePos.y + (itemTf.height + this.space) * pos.x;   // height
        // console.log(pos, _x, _y);
        item.setPosition(_x, _y, 0);
    }

    /**
     * 2个位置的方块互换
     * @param pos1 
     * @param pos2 
     */
    private replace(pos1:Vec2, pos2:Vec2) {
        let _t1 = this.picStatus[pos1.x][pos1.y];
        this.picStatus[pos1.x][pos1.y] = this.picStatus[pos2.x][pos2.y];
        this.picStatus[pos2.x][pos2.y] = _t1;

        let _t2 = this.picArray[pos1.x][pos1.y];
        this.picArray[pos1.x][pos1.y] = this.picArray[pos2.x][pos2.y];
        this.picArray[pos2.x][pos2.y] = _t2;
        if(this.picArray[pos1.x][pos1.y] != null)
            this.calcPicPosition(pos1, this.picArray[pos1.x][pos1.y]);
        if(this.picArray[pos2.x][pos2.y] != null)
            this.calcPicPosition(pos2, this.picArray[pos2.x][pos2.y]);
    }

    private win() {
        for (let x = 0; x < this.picStatus.length; x++) {
            for (let y = 0; y < this.picStatus[x].length; y++) {
                if (x == this.picStatus.length - 1 && y == this.picStatus.length - 1) {
                    break;
                }
                // 判断{0,4}这个点的值为0
                if (x == 0 && y == this.picStatus.length - 1 && this.picStatus[x][y] == 0) {
                    continue;
                }

                if (this.picStatus[x][y] != this.calcPicValue(x, y)) {
                    return false;
                }
            }
        }
        return true;
    }

    private calcPicValue(x: number, y: number) {
        return (x + 1) * 100 + (y + 1);
    }
}
